// sgu323
// 题意：
// 给定一个n(<=2000)个点, k(<=200000)无向图，每条边有一个颜色以及
// 修改成别的颜色的费用。现在想要一个生成树，使得所有边颜色一样，
// 问最小费用。颜色数m(<=2000)。
//
// 题解：
// 先不管颜色，把修改颜色的费用当边权求出一个最小生成树，把这些边存下来，
// 然后枚举颜色，把这个颜色的边先加进去，然后用之前求出来的边再求最小生成树。
//
// 为什么是这样呢？反证法一下就行。
//
// run: $exec < input
#include <iostream>
#include <algorithm>
#include <vector>

struct edge { int from, to, own, cost, id; };
bool operator<(edge const & a, edge const & b) { return a.cost < b.cost; }

int const maxn = 2007;
int father[maxn];
int n, m, k;
std::vector<edge> e;
std::vector<edge> tree;
std::vector<std::vector<edge>> g;

void init_father() { for (int i = 1; i <= n; i++) father[i] = i; }
int get_father(int x) { return x == father[x] ? x : father[x] = get_father(father[x]); }
void set_union(int u, int v)
{
	int tu = get_father(u);
	int tv = get_father(v);
	if (tu != tv) father[tu] = tv;
}

int main()
{
	std::ios::sync_with_stdio(false);
	std::cin >> n >> m >> k;
	g.resize(m + 1); e.resize(k);
	for (int i = 0; i < k; i++) {
		std::cin >> e[i].from >> e[i].to >> e[i].own >> e[i].cost;
		e[i].id = i + 1;
		g[e[i].own].push_back(e[i]);
	}
	init_father();
	std::sort(e.begin(), e.end());
	for (auto i : e) {
		if (get_father(i.from) == get_father(i.to)) continue;
		set_union(i.from, i.to);
		tree.push_back(i);
	}
	long long p = (1ll) << 44, r;
	std::vector<int> ans;
	for (int i = 1; i <= m; i++) {
		init_father();
		for (auto j : g[i]) set_union(j.from, j.to);
		long long tmp = 0;
		std::vector<int> tt;
		for (auto j : tree) {
			if (j.own == i || get_father(j.from) == get_father(j.to)) continue;
			set_union(j.from, j.to);
			tmp += j.cost;
			tt.push_back(j.id);
		}
		if (tmp < p) { p = tmp; ans = tt; r = i; }
	}
	std::cout << p << " " << r << " " << ans.size() << "\n";
	for (auto i : ans) std::cout << i << "\n";
}

